/*
 * PatientReihung.java
 * 
 *  author: Daniel Rudigier
 *    date: 20.05.2008
 * 
 * 
 */
package ocumed.teams.teamb.application;

import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import ocumed.teams.IArzt;
import ocumed.teams.IOcumed;
import ocumed.teams.IPatient;
import ocumed.teams.IPersistence;
import ocumed.teams.IWarteposition;
import ocumed.teams.IWarteschlange;
import ocumed.teams.OcumedFactory;
import ocumed.teams.PersistenceFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * patient queue use-case controller
 * 
 * @author Daniel Rudigier
 *
 */
public class PatientReihung {  
    private static final String onToday = "heute";
    private static final Log log = LogFactory.getLog(PatientReihung.class);
    
    private IOcumed dh;         // catalog instance
    private IPersistence ph;    // persistence instance
    
    private HashMap<Integer, IArzt> assigned;
    
    /**
     * constructor
     * 
     */
    public PatientReihung() {
        dh = OcumedFactory.getInstance();
        ph = PersistenceFactory.getInstance();
        
        assigned = new HashMap<Integer, IArzt>();
        dh.update();
    }
    
    /**
     * transform doctor list into id list for gui
     * 
     * @return
     */
    public List<Integer> getAerzte() {
        log.debug("gui request: getAerzte()");
        
        List<Integer> ids = new Vector<Integer>();
        for (IArzt a : dh.getAerzte()) {
            ids.add(a.getBenutzerid());
        }
        
        return ids;
    }
    
    /**
     * get the queue for a doctor
     * 
     * @param arztId
     * @return a list of patient id's
     */
    public List<Integer> getWarteschlange(int arztId) {
        log.debug("gui request: getWarteschlange() for " + arztId);
        
        List<Integer> q = new Vector<Integer>(); 
        for (IWarteposition w : getW(arztId).getWartepositionen()) {
            q.add(w.getPatient().getPatientid());
            assigned.put(w.getPatient().getPatientid(), w.getArzt());
        }
        
        return q;
    }

    /**
     * get the patient for an patient id
     * 
     * @param patientId
     * @return
     */
    public String getPatient(int patientId) {
        log.debug("gui request: getPatient() for " + patientId);
        IPatient p = dh.getiPatient(patientId); 
        return p.getPatientvorname().charAt(0) + ". " + p.getPatientnachname();
    }
    
    /**
     * get the time in queue for a specific patient. 
     * (not implemented yet)
     * 
     * @param patientId
     * @return
     */
    public String getUhrzeit(int patientId) {
        log.debug("gui request: getUhrzeit() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        //IArzt a = lookupArztByPatient(patientId);
        
        // TODO: lookup an appointment for today, that could match the patient
        // TODO: does this make any sense and is it really needed?
        
        // lookup an appointment that could match
        /*
        TreeSet<ITermin> forToday = new TreeSet<ITermin>();
        for (ITermin t : p.getiTermins()) {
            // lookup if they are from today
        }
        */
        
        return onToday;
    }
    
    /**
     * return the doctor name
     * 
     * @param arztId
     * @return
     */
    public String getArztName(int arztId) {
        log.debug("gui request: getArztName() for " + arztId);        
        IArzt a = dh.getiArzt(arztId);
        
        String ret = a.getBenutzervorname().charAt(0) + ". " + a.getBenutzernachname();
        return ret;
    }
    

    /**
     * 
     * @param patientId
     */
    public void hoch(int patientId) {
        log.debug("gui request: hoch() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = assigned.get(p.getPatientid());
        movePosition(a, p, true, false);
    }
    
    /**
     * 
     * @param patientId
     */
    public void runter(int patientId) {
        log.debug("gui request: runter() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = assigned.get(p.getPatientid());
        movePosition(a, p, false, false);
    }

    /**
     * 
     * @param patientId
     */
    public void erster(int patientId) {
        log.debug("gui request: erster() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = assigned.get(p.getPatientid());
        movePosition(a, p, true, true);
    }
    
    /**
     * 
     * @param patientId
     */
    public void letzter(int patientId) {
        log.debug("gui request: letzter() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = assigned.get(p.getPatientid());
        movePosition(a, p, false, true);
    }
    
    /**
     * enqueue a patient using the default doctor
     * 
     * @param patientId
     * @return true on success
     */
    public Boolean einreihen(int patientId) {
        log.debug("gui request: einreihen() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = p.getiBenutzerByArztid();
        IWarteposition wp = a.getiWarteschlange().einreihen(p);
        
        if (wp != null) {
            ph.put(wp);
            return true;
        }
        return false;
    }
    
    /**
     * enqueue a patient using a given doctor
     * 
     * @param patientId
     * @param arztId
     * @return
     */
    public Boolean einreihen(int patientId, int arztId) {
        log.debug("gui request: einreihen() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = dh.getiArzt(arztId);
        IWarteposition wp = a.getiWarteschlange().einreihen(p);
        
        if (wp != null) {
            ph.put(wp);
            return true;
        }
        return false;
    }
    
    
    /**
     * dequeue a patient using the default doctor
     * 
     * @param patientId
     */
    public void ausreihen(int patientId) {
        log.debug("gui request: ausreihen() for " + patientId);
        IPatient p = dh.getiPatient(patientId);
        IArzt a = assigned.get(p.getPatientid());
        IWarteposition wp = getW(a.getBenutzerid()).ausreihen(p);
        
        if (wp != null) {
            ph.delete(wp);
        }
    }
    
    /**
     * move a position and synchronize with db
     * 
     * @param a
     * @param p
     * @param bus
     * @param c
     */
    private void movePosition(IArzt a, IPatient p, boolean b, boolean c) {
        IWarteposition[] affected = getW(a.getBenutzerid()).position(p, b, c);
        if (affected != null && affected.length == 2) {
            log.debug("modified positions");
            ph.put(affected[0]);
            ph.put(affected[1]);
        }
    }
    
    /**
     * 
     * @param arztId
     * @return
     */
    private IWarteschlange getW(int arztId) {
        // IWarteschlange w = dh.getiWarteschlange(arztId);
        IWarteschlange w = dh.getiArzt(arztId).getiWarteschlange();
        return w;
    }

}
